Português

Desbloqueie o poder do padrão Render Props do React. Aprenda como ele promove a reutilização de código, a composição de componentes e a separação de preocupações.

React Render Props Pattern: Flexible Component Logic for a Global Audience

No cenário em constante evolução do desenvolvimento front-end, particularmente dentro do ecossistema React, os padrões arquiteturais desempenham um papel crucial na construção de componentes escaláveis, mantiveis e reutilizáveis. Entre esses padrões, o Render Props se destaca como uma técnica poderosa para compartilhar código e lógica entre componentes React. Este post de blog tem como objetivo fornecer uma compreensão abrangente do padrão Render Props, seus benefícios, casos de uso e como ele contribui para a construção de aplicações robustas e adaptáveis para um público global.

What are Render Props?

Um Render Prop é uma técnica simples para compartilhar código entre componentes React usando uma prop cujo valor é uma função. Em essência, um componente com um render prop recebe uma função que retorna um elemento React e chama essa função para renderizar algo. O componente não decide o que renderizar diretamente; ele delega essa decisão para a função render prop, fornecendo a ela acesso ao seu estado interno e lógica.

Considere este exemplo básico:


class DataProvider extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    // Simulate fetching data
    setTimeout(() => {
      this.setState({ data: 'Some data from an API' });
    }, 1000);
  }

  render() {
    return this.props.render(this.state.data);
  }
}

function MyComponent() {
  return (
     (
        
{data ?

Data: {data}

:

Loading...

}
)} /> ); }

Neste exemplo, DataProvider busca dados e os passa para a função prop render fornecida por MyComponent. MyComponent então usa esses dados para renderizar seu conteúdo.

Why Use Render Props?

O padrão Render Props oferece várias vantagens importantes:

Real-World Use Cases and International Examples

O padrão Render Props é valioso em uma variedade de cenários. Aqui estão alguns casos de uso comuns com exemplos que consideram um público global:

1. Mouse Tracking

Imagine que você deseja rastrear a posição do mouse em uma página da web. Usando um Render Prop, você pode criar um componente MouseTracker que fornece as coordenadas do mouse para seus filhos.


class MouseTracker extends React.Component {
  constructor(props) {
    super(props);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove = event => {
    this.setState({ x: event.clientX, y: event.clientY });
  };

  render() {
    return (
      
{this.props.render(this.state)}
); } } function MyComponent() { return ( (

The mouse position is ({x}, {y})

)} /> ); }

Isso é facilmente adaptado para aplicações internacionalizadas. Por exemplo, imagine um aplicativo de desenho usado por artistas no Japão. As coordenadas do mouse podem ser usadas para controlar os traços do pincel:


 (
    
  )}
/>

2. Fetching Data from APIs

Buscar dados de APIs é uma tarefa comum no desenvolvimento web. Um componente Render Prop pode lidar com a lógica de busca de dados e fornecer os dados para seus filhos.


class APIFetcher extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null, loading: true, error: null };
  }

  async componentDidMount() {
    try {
      const response = await fetch(this.props.url);
      const data = await response.json();
      this.setState({ data: data, loading: false });
    } catch (error) {
      this.setState({ error: error, loading: false });
    }
  }

  render() {
    return this.props.render(this.state);
  }
}

function MyComponent() {
  return (
     {
        if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return
{JSON.stringify(data, null, 2)}
; }} /> ); }

Isso é particularmente útil ao lidar com dados localizados. Por exemplo, imagine exibir taxas de câmbio para usuários em diferentes regiões:


 {
    if (loading) return 

Loading exchange rates...

; if (error) return

Error fetching exchange rates.

; return (
    {Object.entries(data.rates).map(([currency, rate]) => (
  • {currency}: {rate}
  • ))}
); }} />

3. Form Handling

Gerenciar o estado e a validação de formulários pode ser complexo. Um componente Render Prop pode encapsular a lógica do formulário e fornecer o estado e os manipuladores do formulário para seus filhos.


class FormHandler extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '', error: null };
  }

  handleChange = event => {
    this.setState({ value: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    if (this.state.value.length < 5) {
      this.setState({ error: 'Value must be at least 5 characters long.' });
      return;
    }
    this.setState({ error: null });
    this.props.onSubmit(this.state.value);
  };

  render() {
    return this.props.render({
      value: this.state.value,
      handleChange: this.handleChange,
      handleSubmit: this.handleSubmit,
      error: this.state.error
    });
  }
}

function MyComponent() {
  return (
     alert(`Submitted value: ${value}`)}
      render={({ value, handleChange, handleSubmit, error }) => (
        
{error &&

{error}

}
)} /> ); }

Considere adaptar as regras de validação do formulário para atender aos formatos de endereço internacionais. O componente `FormHandler` pode permanecer genérico, enquanto o render prop define a validação específica e a lógica de UI para diferentes regiões:


 sendAddressToServer(address)}
  render={({ value, handleChange, handleSubmit, error }) => (
    
{/* Fields for address, adapting to regional formats */} {error &&

{error}

}
)} />

4. Feature Flags and A/B Testing

Render Props também podem ser usados para gerenciar feature flags e conduzir testes A/B. Um componente Render Prop pode determinar qual versão de um recurso renderizar com base no usuário atual ou em um sinalizador gerado aleatoriamente.


class FeatureFlag extends React.Component {
  constructor(props) {
    super(props);
    this.state = { enabled: Math.random() < this.props.probability };
  }

  render() {
    return this.props.render(this.state.enabled);
  }
}

function MyComponent() {
  return (
     {
        if (enabled) {
          return 

New Feature!

; } else { return

Old Feature

; } }} /> ); }

Ao realizar testes A/B para um público global, é importante segmentar os usuários com base no idioma, região ou outros dados demográficos. O componente `FeatureFlag` pode ser modificado para considerar esses fatores ao determinar qual versão de um recurso exibir:


 {
    return isEnabled ?  : ;
  }}
/>

Alternatives to Render Props: Higher-Order Components (HOCs) and Hooks

Embora Render Props seja um padrão poderoso, existem abordagens alternativas que podem alcançar resultados semelhantes. Duas alternativas populares são Higher-Order Components (HOCs) e Hooks.

Higher-Order Components (HOCs)

Um Higher-Order Component (HOC) é uma função que recebe um componente como argumento e retorna um novo componente aprimorado. Os HOCs são comumente usados para adicionar funcionalidade ou lógica aos componentes existentes.

Por exemplo, o HOC withMouse poderia fornecer funcionalidade de rastreamento do mouse a um componente:


function withMouse(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { x: 0, y: 0 };
    }

    handleMouseMove = event => {
      this.setState({ x: event.clientX, y: event.clientY });
    };

    render() {
      return (
        
); } }; } function MyComponent(props) { return (

The mouse position is ({props.mouse.x}, {props.mouse.y})

); } const EnhancedComponent = withMouse(MyComponent);

Embora os HOCs ofereçam reutilização de código, eles podem levar a conflitos de nomes de propriedades e tornar a composição de componentes mais difícil, um fenômeno conhecido como "wrapper hell".

Hooks

React Hooks, introduzidos no React 16.8, fornecem uma maneira mais direta e expressiva de reutilizar a lógica stateful entre os componentes. Os Hooks permitem que você "se conecte" aos recursos de estado e ciclo de vida do React a partir de componentes de função.

Usando o hook useMousePosition, a funcionalidade de rastreamento do mouse pode ser implementada da seguinte forma:


import { useState, useEffect } from 'react';

function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({ x: event.clientX, y: event.clientY });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return mousePosition;
}

function MyComponent() {
  const mousePosition = useMousePosition();
  return (
    

The mouse position is ({mousePosition.x}, {mousePosition.y})

); }

Os Hooks oferecem uma maneira mais limpa e concisa de reutilizar a lógica stateful em comparação com Render Props e HOCs. Eles também promovem melhor legibilidade e manutenção do código.

Render Props vs. Hooks: Choosing the Right Tool

Decidir entre Render Props e Hooks depende dos requisitos específicos do seu projeto e de suas preferências pessoais. Aqui está um resumo de suas principais diferenças:

Best Practices for Using Render Props

Para usar efetivamente o padrão Render Props, considere as seguintes práticas recomendadas:

Conclusion

O padrão Render Props é uma técnica valiosa para construir componentes React flexíveis e reutilizáveis. Ao encapsular a lógica e fornecê-la aos componentes por meio de um render prop, você pode promover a reutilização de código, a composição de componentes e a separação de preocupações. Embora os Hooks ofereçam uma alternativa mais moderna e muitas vezes mais simples, os Render Props permanecem uma ferramenta poderosa no arsenal do desenvolvedor React, particularmente ao lidar com código legado ou cenários que exigem controle refinado sobre o processo de renderização.

Ao compreender os benefícios e as práticas recomendadas do padrão Render Props, você pode construir aplicações robustas e adaptáveis que atendem a um público global diversificado, garantindo uma experiência de usuário consistente e envolvente em diferentes regiões e culturas. A chave é escolher o padrão certo – Render Props, HOCs ou Hooks – com base nas necessidades específicas do seu projeto e na experiência da sua equipe. Lembre-se de sempre priorizar a legibilidade, a manutenibilidade e o desempenho do código ao tomar decisões arquitetônicas.